home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / cpucheck.zip / CHIPTYPE.ASM < prev    next >
Assembly Source File  |  1990-04-30  |  10KB  |  251 lines

  1. page    60,132
  2. title   chiptype() - CPU and Math Coprocessor (NDP) Type Check
  3.  
  4. ;   Turbo Pascal 4.0 or later and Quick Pascal 1.0 or later calling convention:
  5. ;   Requires MASM 5.0 or later.
  6. ;
  7. ;       function chiptype : integer;
  8. ;
  9. ;   returns:
  10. ;
  11. ;       tucked away neatly in your AX....
  12. ;
  13. ;       you get back   8x if an 8088/8086
  14. ;                     18x if an 80186/80188
  15. ;                     28x if an 80286
  16. ;                     38x if an 80386
  17. ;                     48x if an 80486
  18. ;                     20x for a NEC V20/V30
  19. ;                AND
  20. ;                     xx0 if NO NDP is found
  21. ;                     xx1 if an 8087
  22. ;                     xx2 if an 80287
  23. ;                     xx3 for an 80387
  24. ;                     xx4 for built-in coprocessor on 80486
  25. ;
  26. ;   OR.....
  27. ;
  28. ;   >>> A return of 280 means you got an 80286 machine with no NDP, <<<
  29. ;   >>> 383 means you have an 80386/80387 rig to work with, and a   <<<
  30. ;   >>> return of 81 sez that you have 8088/8086 CPU with an 8087.  <<<
  31. ;   >>> A 200 tells you that you got an NEC V20/V30 without an NDP. <<<
  32. ;   >>> ETC., Etc., etc.                                            <<<
  33. ;   >>> Presence of an 80486 always returns 80484                   <<<
  34. ;
  35. ;   NOTE:
  36. ;
  37. ;       There are lotsa ways of handling the way this function returns
  38. ;       it's data.  For my purposes, I have elected this one because
  39. ;       it requires only int arithmetic on the caller's end to extract
  40. ;       all the info I need from the return value.  I think that I'm
  41. ;       well enough 'commented' in the following code so that you will
  42. ;       be able to tinker and Putz until you find the best return tech-
  43. ;       nique for Ur purposes without having to reinvent the wheel.
  44. ;
  45. ;   REFERENCES:
  46. ;
  47. ;     _chiptype is made up of two PROC's, cpu_type and ndp_type.
  48. ;
  49. ;       cpu_type is based on uncopyrighted, published logic by
  50. ;         Clif (that's the way he spells it) Purkiser of Intel -
  51. ;         Santa Clara.
  52. ;
  53. ;       ndp_type is adopted from Ted Forgeron's article in PC
  54. ;         Tech Journal, Aug '87 p43.
  55. ;
  56. ;     In the event of subsequent republication of this function,
  57. ;       please carry forward reference to these two gentlemen as
  58. ;       original authors.
  59. ;
  60. ;       Copr. 1987      Pat Shea - Psi! (that Copr. is on there cuz my
  61. ;                                        lawyer sez I should, but feel
  62. ;                                        free to hack away!!!    pats.)
  63. ;
  64. ;       Add detection of 80486 chip per page 3-42, i486 Microprocessor
  65. ;    Programmer's Reference Manual, Intel, 1990, Order Number 240486-001.
  66. ;       Ben Myers
  67.  
  68. CODE    SEGMENT BYTE PUBLIC 'CODE'
  69.     ASSUME  CS:CODE
  70.  
  71.     PUBLIC  chiptype
  72.  
  73. chiptype       PROC FAR
  74.  
  75. control EQU    WORD PTR [bp-2] ; control word needed for the NDP test
  76.  
  77.     push   BP             ; save where context at
  78.     mov    BP,SP          ;   entry.....
  79.     push   DI
  80.     push   SI
  81.     push   CX             ; not really needed for MSC but kinda
  82.                   ;   nice to do cuz someone else might
  83.                   ;   want to use the function and we do
  84.                   ;   use CX later on
  85.  
  86.     call   cpu_type       ; find out what kinda CPU you got and
  87.                   ;   and save it in DX for future reference
  88.     cmp    DX,484         ; test for i486
  89.     jnz    Not_486        ; Nope.
  90.     mov    AX,DX          ; Yes, don't test for coprocessor.
  91.     jmp    short Got_486  ; Clean up and exit.
  92. Not_486:
  93.  
  94.     call   ndp_type       ; check for math coprocessor (NDP) type
  95.                   ;   and hold that result in AX
  96.  
  97.     add    AX,DX          ; add the two results together and hold
  98.                   ;   'em in AX for Ur return to the caller
  99.  
  100. Got_486:
  101.     pop    CX             ; put things back the way that you
  102.     pop    SI             ;   found 'em when you started this
  103.     pop    DI             ;   little drill off.....
  104.     pop    BP
  105.                   ; AND
  106.     ret                   ; go back to where you came from....
  107.                   ;   ( ===>  the calling program )
  108.                   ;   with Ur results sittin' in AX !!
  109. chiptype       endp
  110.  
  111.  
  112. cpu_type       PROC NEAR
  113.  
  114.     pushf                 ; pump Ur flags register onto the stack
  115.     xor    DX,DX          ; blow out Ur DX and AX to start off
  116.     xor    AX,AX          ;   with a clean slate
  117.     push   AX             ; put AX on the stack
  118.     popf                  ; bring it back in Ur flags
  119.     pushf                 ; try to set bits 12 thru 15 to a zero
  120.     pop    AX             ; get back Ur flags word in AX
  121.     and    AX, 0f000h     ; if bits 12 thru 15 are set then you got
  122.     cmp    AX, 0f000h     ;   an Intel 8018x or a 808x or maybe even
  123.     jz     dig            ;   a NEC V20/V30 ??? - gotta look more...
  124.  
  125. ; OTHERWISE....
  126. ;   Here's the BIG one.... 'tells the difference between an 80286 and
  127. ;   an 80386 !!
  128.  
  129.     mov    AX, 07000h     ; try to set FLAG bits 12 thru 14
  130.                   ;   - NT, IOPL
  131.     push   AX             ; put it onto the stack
  132.     popf                  ;   and try to pump 07000H into Ur flags
  133.     pushf                 ; push Ur flags, again
  134.     pop    AX             ;   and bring back AX for a compare
  135.     and    AX,07000h      ; if Ur bits 12 thru 14 are set
  136.     jnz    got386         ;   then Ur workin' with an 80386
  137.     mov    DX, 0280       ; save 280 in DX cuz it's an 80286
  138.     jmp    SHORT CPUbye   ;   and bail out
  139.  
  140. got386: ; At least a 386.  See if i486
  141. ; BEGIN 486 detection logic
  142.     .386
  143.     mov    edx,esp        ; Save current stack pointer to align it.
  144.     and    esp, not 3     ; Align stack to avoid AC fault.
  145.     pushfd              ; Push EFLAGS.
  146.     pop    eax          ; Get EFLAGS value.
  147.     mov    ecx,eax          ; Save original EFLAGS.
  148.     xor    eax,40000h     ; Flip AC bit in EFLAGS.
  149.     push   eax          ; Copy to EFLAGS
  150.     popfd              ; ...
  151.     pushfd              ; Get new EFLAGS value.
  152.     pop    eax            ; Put into eax.
  153.     xor    eax,ecx          ; See if AC bit has changed.
  154.                   ; EAX=40000h if 386 CPU, 0 if i486 CPU
  155.     shr    eax,18          ; Set EAX=1 if 386 CPU, 0 if i486 CPU
  156.     push   ecx            ; Original EFLAGS value
  157.     popfd              ; restored.
  158.     mov    esp,edx          ; Restore original stack pointer.
  159.     and    eax,1          ; Mask out all other bits.
  160.     .8086
  161.     jz     SHORT CPU386   ;
  162.     mov    DX,484         ; Identify i486 with coprocessor.
  163.     jmp    SHORT CPUbye   ;   and bail out.
  164. CPU386:
  165.     mov    DX,380         ; Identify 386.
  166.     jmp    SHORT CPUbye   ;   and bail out.
  167.  
  168. ; here's we try to figger out whether it's an 80188/80186, an 8088/8086
  169. ;   or an NEC V20/V30 - 'couple of slick tricks from Clif Purkiser.....
  170.  
  171. dig:    mov    AX, 0ffffh     ; load up AX
  172.     mov    CL, 33         ; HERE's the FIRST TRICK.... this will
  173.                   ;   shift everything 33 times if it's
  174.                   ;   8088/8086, or once for a 80188/80186!
  175.     shl    AX, CL         ; on a shift of 33, all bits get zeroed
  176.     jz     digmor         ;   out so if anything is left ON it's
  177.                   ;   gotta be an 80188/80186
  178.     mov    DX,0180        ; save 180 in DX cuz it's an 80188/80186
  179.     jmp    SHORT CPUbye   ;   and bail out
  180.  
  181. digmor: xor    AL,AL          ; clean out AL to set ZF
  182.     mov    AL,40h         ; ANOTHER TRICK.... mul on an NEC duz NOT
  183.     mul    AL             ;   effect the zero flag BUT on an Intel
  184.     jz     gotNEC         ;   8088/8086, the zero flag gets thrown
  185.     mov    DX,0080        ; 80 into DX cuz it's an Intel 8088/8086
  186.     jmp    SHORT CPUbye   ;   and bail out
  187.  
  188. gotNEC: mov    DX,0200        ; it's an NEC V20/V30 so save 200 in DX
  189.  
  190. CPUbye: popf                  ; putchur flags back to where they were
  191.     ret                   ;   and go back to where you came from
  192.                   ;   (i.e., ===>  chiptype) with the CPU type
  193.                   ;   tucked away in DX for future reference
  194. cpu_type       endp
  195.  
  196. ; Check for an NDP.
  197. ;
  198.  
  199. ndp_type       PROC NEAR
  200.  
  201. do_we:  fninit                          ; try to initialize the NDP
  202.     mov    byte ptr control+1,0     ; clear memory byte
  203.     fnstcw control                  ; put control word in memory
  204.     mov    AH,byte ptr [control+1]  ; iff AH is 03h, you got
  205.     cmp    AH,03h                   ;   an NDP on board !!
  206.     je     chk_87                   ; found somethin', keep goin'
  207.     xor    AX,AX                    ; clean out AX to show a zero
  208.     jmp    SHORT NDPbye             ;   return (i.e., no NDP)
  209.  
  210. ; 'got an 8087 ??
  211.  
  212. chk_87: and    control,NOT 0080h        ; turn ON interrupts (IEM = 0)
  213.     fldcw  control                  ; load control word
  214.     fdisi                           ; turn OFF interrupts (IEM = 1)
  215.     fstcw  control                  ; store control word
  216.     test   control,0080h            ; iff IEM=1, 8087
  217.     jz     chk287                   ; 'guess not!  March on....
  218.     mov    AX,0001                  ; set up for a 1 return to
  219.     jmp    SHORT NDPbye             ;   show an 8087 is on board
  220.  
  221. ; if not.... would you believe an 80287 maybe ??
  222.  
  223. chk287: finit                 ; set default infinity mode
  224.     fld1                  ; make infinity
  225.     fldz                  ;   by dividing
  226.     fdiv                  ;   1 by zero !!
  227.     fld    st             ; now make a
  228.     fchs                  ;   negative infinity
  229.     fcompp                ; compare Ur two infinities
  230.     fstsw  control        ; iff, for 8087 or 80287
  231.     fwait                 ; sit tight 'til status word is put away
  232.     mov    AX,control     ; getchur control word
  233.     sahf                  ; putchur AH into flags
  234.     jnz    got387         ; NO GOOD.... march on !!
  235.     mov    AX,0002        ; gotta be a 80287 cuz we already tested
  236.     jmp    SHORT NDPbye   ;   for an 8087
  237.  
  238. ; We KNOW that there is an NDP on board otherwise we would have bailed
  239. ; out after 'do_we'.  It isn't an 8087 or an 80287 or we wouldn't have
  240. ; gotten this far.  It's gotta be an 80387 !!
  241.  
  242. got387: mov    AX,0003        ; call it an 80387 and return 3
  243.  
  244. NDPbye: ret                   ; and go back where you came from
  245.                   ;   (i.e., ===>  chiptype) carrying the NDP
  246.                   ;   type in Ur AX register
  247. ndp_type       endp
  248.  
  249. CODE    ends
  250.     end
  251.